package com.ruoyi.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.page.PageUtils;
import com.ruoyi.common.utils.page.Query;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.web.domain.*;
import com.ruoyi.web.domain.vo.QueryVo;
import com.ruoyi.web.domain.wx.AppQueryVo;
import com.ruoyi.web.mapper.*;
import com.ruoyi.web.service.IPoiApplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class PoiApplyServiceImpl extends ServiceImpl<PoiApplyMapper, PoiApply> implements IPoiApplyService {

    @Autowired
    private PoiApplyItemMapper poiApplyItemMapper;

    @Autowired
    private PoiApplyImageMapper poiApplyImageMapper;

    @Autowired
    private UcQuoProjectMapper ucQuoProjectMapper;

    @Autowired
    private UcMyFlowMapper ucMyFlowMapper;

    @Autowired
    private UcQuoTableMapper ucQuoTableMapper;

    @Autowired
    private SysUserMapper sysUserMapper;


    @Override
    public PageUtils listByPage(QueryVo queryVo) {
        QueryWrapper<PoiApply> qw =new QueryWrapper<>();

        if(queryVo.getQUserId()!=null){
            qw.eq("user_id",queryVo.getQUserId());
        }
        if(!StringUtils.isEmpty(queryVo.getQIds1())){
            qw.eq("dept_id",queryVo.getQIds1().get(queryVo.getQIds1().size()-1));
        }
        if(!StringUtils.isEmpty(queryVo.getQTimeStartList())){
            qw.le("time_start",queryVo.getQTimeStartList().get(1)+" 23:59:59");
            qw.ge("time_start",queryVo.getQTimeStartList().get(0)+" 00:00:00");
        }
        if(queryVo.getQStatus()!=null){
            qw.ge("apply_status",queryVo.getQStatus());
            qw.le("apply_status",queryVo.getQStatus()+5);
        }
        if(queryVo.getQFrom()!=null){
            qw.eq("quota_from",queryVo.getQFrom());
        }

        if(!StringUtils.isEmpty(queryVo.getQKey())){
            qw.and((wrapper)->{
                wrapper.or().like("nick_name",queryVo.getQKey());
            });
        }

        if("descending".equals(queryVo.getIsAsc())){
            qw.orderBy(true,false,queryVo.getOrderByColumn()).orderBy(true,false,"id");
        }else if("ascending".equals(queryVo.getIsAsc())){
            qw.orderBy(true,true,queryVo.getOrderByColumn()).orderBy(true,false,"id");
        }else{
            qw.orderBy(true,false,"id");
        }

        IPage<PoiApply> page = this.page(new Query<PoiApply>().getPage(BeanUtil.beanToMap(queryVo)), qw);

        return new PageUtils(page);
    }



    @Override
    public Long saveTry(PoiApply poiApply) {

        Date date = new Date();
        SysUser user = SecurityUtils.getLoginUser().getUser();

        if(poiApply.getId()!=null && poiApply.getId()!=0L){

            QueryWrapper<PoiApplyItem> qwPoiApplyItem = new QueryWrapper<>();
            qwPoiApplyItem.eq("apply_id",poiApply.getId());
            List<PoiApplyItem> oldPoiApplyItems = poiApplyItemMapper.selectList(qwPoiApplyItem);

            List<UcQuoProjectItem> newUcQuoProjectItems = poiApply.getUcQuoProjects().stream()
                    .flatMap(ucQuoProject -> ucQuoProject.getUcQuoProjectItems().stream())
                    .filter(ucQuoProjectItem -> (ucQuoProjectItem.getNum() != null && ucQuoProjectItem.getNum() > 0)).collect(Collectors.toList());


            List<UcQuoProjectItem> addUcQuoProjectItems = BeanUtils.compareDifference(
                    newUcQuoProjectItems,
                    UcQuoProjectItem::getId,
                    oldPoiApplyItems,
                    PoiApplyItem::getItemId
            );

            List<PoiApplyItem> deletePoiApplyItems = BeanUtils.compareDifference(
                    oldPoiApplyItems,
                    PoiApplyItem::getItemId,
                    newUcQuoProjectItems,
                    UcQuoProjectItem::getId
            );

            List<UcQuoProjectItem> updateUcQuoProjectItems = BeanUtils.compareSame(
                    newUcQuoProjectItems,
                    UcQuoProjectItem::getId,
                    oldPoiApplyItems,
                    PoiApplyItem::getItemId
            );


            for (UcQuoProjectItem ucQuoProjectItem : addUcQuoProjectItems) {

                UcQuoProject ucQuoProject = ucQuoProjectMapper.selectById(ucQuoProjectItem.getProjectId());
                PoiApplyItem poiApplyItem = new PoiApplyItem();
                poiApplyItem.setUserId(poiApply.getUserId());
                poiApplyItem.setApplyId(poiApply.getId());
                poiApplyItem.setProjectId(ucQuoProject.getId());
                poiApplyItem.setProjectName(ucQuoProject.getName());
                poiApplyItem.setItemId(ucQuoProjectItem.getId());
                poiApplyItem.setItemName(ucQuoProjectItem.getName());
                poiApplyItem.setQuotaType(ucQuoProject.getQuotaType());
                poiApplyItem.setChooseType(ucQuoProject.getChooseType());
                poiApplyItem.setQuotaFrom(10);
                poiApplyItem.setLimitType(ucQuoProjectItem.getLimitType());
                poiApplyItem.setLimitMax(ucQuoProjectItem.getLimitMax());
                poiApplyItem.setContent(ucQuoProjectItem.getContent());
                if(poiApplyItem.getChooseType() == 1){
                    poiApplyItem.setNum(1);
                    poiApplyItem.setUnitScore(ucQuoProjectItem.getScore());
                    poiApplyItem.setScore(ucQuoProjectItem.getScoreText());
                }else{
                    poiApplyItem.setNum(ucQuoProjectItem.getNum());
                    poiApplyItem.setUnitScore(ucQuoProjectItem.getScore());
                    poiApplyItem.setScore(poiApplyItem.getNum() * poiApplyItem.getUnitScore());
                }
                poiApplyItem.setTimeStart(poiApply.getTimeStart());
                poiApplyItem.setYear(poiApply.getYear());
                poiApplyItem.setQuarter(poiApply.getQuarter());
                poiApplyItem.setMonth(poiApply.getMonth());
                poiApplyItem.setDelStatus(1);
                poiApplyItemMapper.insert(poiApplyItem);
            }

            for (PoiApplyItem poiApplyItem : deletePoiApplyItems) {
                poiApplyItemMapper.deleteById(poiApplyItem);
            }

            for (UcQuoProjectItem ucQuoProjectItem : updateUcQuoProjectItems) {

                qwPoiApplyItem = new QueryWrapper<>();
                qwPoiApplyItem.eq("apply_id",poiApply.getId());
                qwPoiApplyItem.eq("item_id",ucQuoProjectItem.getId());
                PoiApplyItem poiApplyItem = poiApplyItemMapper.selectOne(qwPoiApplyItem);
                poiApplyItem.setContent(ucQuoProjectItem.getContent());
                if(poiApplyItem.getChooseType() == 1){
                    poiApplyItem.setNum(1);
                    poiApplyItem.setUnitScore(ucQuoProjectItem.getScore());
                    poiApplyItem.setScore(ucQuoProjectItem.getScoreText());
                }else{
                    poiApplyItem.setNum(ucQuoProjectItem.getNum());
                    poiApplyItem.setUnitScore(ucQuoProjectItem.getScore());
                    poiApplyItem.setScore(poiApplyItem.getNum() * poiApplyItem.getUnitScore());
                }
                poiApplyItemMapper.updateById(poiApplyItem);

            }


            QueryWrapper<PoiApplyImage> qwPoiApplyImage = new QueryWrapper<>();
            qwPoiApplyImage.eq("apply_id",poiApply.getId());
            List<PoiApplyImage> oldPoiApplyImageList = poiApplyImageMapper.selectList(qwPoiApplyImage);

            List<String> addString = BeanUtils.compareDifference(
                    poiApply.getImgList(),
                    String::toString,
                    oldPoiApplyImageList,
                    PoiApplyImage::getImage
            );
            List<PoiApplyImage> deletePoiApplyImageList = BeanUtils.compareDifference(
                    oldPoiApplyImageList,
                    PoiApplyImage::getImage,
                    poiApply.getImgList(),
                    String::toString
            );
            for (String s : addString) {
                PoiApplyImage poiApplyImage =new PoiApplyImage();
                poiApplyImage.setDelStatus(1);
                poiApplyImage.setApplyId(poiApply.getId());
                poiApplyImage.setImage(s);
                poiApplyImageMapper.insert(poiApplyImage);
            }
            for (PoiApplyImage poiApplyImage : deletePoiApplyImageList) {
                poiApplyImageMapper.deleteById(poiApplyImage);
            }


        }else{

            poiApply.setDelStatus(1);
            poiApply.setUserId(user.getUserId());
            poiApply.setNickName(user.getNickName());
            poiApply.setDeptId(user.getDeptId());
            poiApply.setDeptName(user.getDept().getDeptName());
            poiApply.setQuotaFrom(10);
            poiApply.setTimeStart(date);
            poiApply.setYear(DateUtils.getYear(poiApply.getTimeStart()));
            poiApply.setQuarter(DateUtils.getQuarter(poiApply.getTimeStart()));
            poiApply.setMonth(DateUtils.getMonth(poiApply.getTimeStart()));
            poiApply.setApplyStatus(100);

            baseMapper.insert(poiApply);

            for (UcQuoProject ucQuoProject : poiApply.getUcQuoProjects()) {

                for (UcQuoProjectItem ucQuoProjectItem : ucQuoProject.getUcQuoProjectItems()) {

                    if(ucQuoProject.getChooseType() !=1 && ucQuoProjectItem.getNum() != null && ucQuoProjectItem.getNum() > 0 ||
                            ucQuoProject.getChooseType() ==1 && ucQuoProjectItem.getScoreText() > 0D){

                        PoiApplyItem poiApplyItem = new PoiApplyItem();
                        poiApplyItem.setUserId(poiApply.getUserId());
                        poiApplyItem.setApplyId(poiApply.getId());
                        poiApplyItem.setProjectId(ucQuoProject.getId());
                        poiApplyItem.setProjectName(ucQuoProject.getName());
                        poiApplyItem.setItemId(ucQuoProjectItem.getId());
                        poiApplyItem.setItemName(ucQuoProjectItem.getName());
                        poiApplyItem.setQuotaType(ucQuoProject.getQuotaType());
                        poiApplyItem.setChooseType(ucQuoProject.getChooseType());
                        poiApplyItem.setQuotaFrom(10);
                        poiApplyItem.setLimitType(ucQuoProjectItem.getLimitType());
                        poiApplyItem.setLimitMax(ucQuoProjectItem.getLimitMax());
                        poiApplyItem.setContent(ucQuoProjectItem.getContent());
                        if(poiApplyItem.getChooseType() == 1){
                            poiApplyItem.setNum(1);
                            poiApplyItem.setUnitScore(ucQuoProjectItem.getScore());
                            poiApplyItem.setScore(ucQuoProjectItem.getScoreText());
                        }else{
                            poiApplyItem.setNum(ucQuoProjectItem.getNum());
                            poiApplyItem.setUnitScore(ucQuoProjectItem.getScore());
                            poiApplyItem.setScore(poiApplyItem.getNum() * poiApplyItem.getUnitScore());
                        }
                        poiApplyItem.setTimeStart(poiApply.getTimeStart());
                        poiApplyItem.setYear(poiApply.getYear());
                        poiApplyItem.setQuarter(poiApply.getQuarter());
                        poiApplyItem.setMonth(poiApply.getMonth());
                        poiApplyItem.setDelStatus(1);
                        poiApplyItemMapper.insert(poiApplyItem);

                    }
                }
            }


            List<PoiApplyImage> poiApplyImageList =new ArrayList<>();
            if(!StringUtils.isEmpty(poiApply.getImgList())){
                poiApply.getImgList().forEach(item ->{
                    PoiApplyImage poiApplyImage =new PoiApplyImage();
                    poiApplyImage.setDelStatus(1);
                    poiApplyImage.setApplyId(poiApply.getId());
                    poiApplyImage.setImage(item);
                    poiApplyImageList.add(poiApplyImage);
                });
            }

            if(!StringUtils.isEmpty(poiApplyImageList)){
                poiApplyImageMapper.insertBatch(poiApplyImageList);
            }
        }

        QueryWrapper<PoiApplyItem> qwPoiApplyItem = new QueryWrapper<>();
        qwPoiApplyItem.eq("apply_id",poiApply.getId());
        List<PoiApplyItem> poiApplyItems = poiApplyItemMapper.selectList(qwPoiApplyItem);

        Integer numItem= 0;
        Integer numTimes= 0;
        Double score = 0D;
        for (PoiApplyItem poiApplyItem : poiApplyItems) {
            numItem++;
            numTimes+=poiApplyItem.getNum();
            score+=poiApplyItem.getScore();
        }
        poiApply.setNumItem(numItem);
        poiApply.setNumTimes(numTimes);
        poiApply.setScore(score);
        baseMapper.updateById(poiApply);

        return poiApply.getId();
    }

    @Override
    @Transactional
    public void insert(PoiApply poiApply) {

        SysUser user = SecurityUtils.getLoginUser().getUser();
        Long id = saveTry(poiApply);

        PoiApply newPoiApply=new PoiApply();
        newPoiApply.setId(id);
        newPoiApply.setApplyStatus(200);

        baseMapper.updateById(newPoiApply);


        UcMyFlow ucMyFlow =new UcMyFlow();
        ucMyFlow.setFlowId(id);
        ucMyFlow.setFlowStatusStart(poiApply.getApplyStatus());
        ucMyFlow.setFlowStatusEnd(newPoiApply.getApplyStatus());
        ucMyFlow.setHandleName(user.getNickName());
        ucMyFlow.setPass(1);
        ucMyFlow.setDelStatus(1);
        ucMyFlowMapper.insert(ucMyFlow);

        QueryVo queryVo = new QueryVo();
        queryVo.setQId(id);
        poiApply = baseMapper.selectByApply(queryVo);

        queryVo = new QueryVo();
        queryVo.setQId(poiApply.getTableId());
        UcQuoTable ucQuoTable = ucQuoTableMapper.searchBayId(queryVo);
        for (UcQuoProject ucQuoProject : ucQuoTable.getUcQuoProjectList()) {
            for (UcQuoProjectItem ucQuoProjectItem : ucQuoProject.getUcQuoProjectItems()) {

                Integer numCanApply = 999;
                LambdaQueryWrapper<PoiApplyItem> lqwPoiApplyItem = new LambdaQueryWrapper<>();
                lqwPoiApplyItem.eq(PoiApplyItem::getItemId,ucQuoProjectItem.getId());
                lqwPoiApplyItem.eq(PoiApplyItem::getUserId,user.getUserId());
                if(ucQuoProjectItem.getLimitType() >=20){
                    numCanApply = ucQuoProjectItem.getLimitMax();
                    lqwPoiApplyItem.eq(PoiApplyItem::getYear,poiApply.getYear());
                }
                if(ucQuoProjectItem.getLimitType() >=30){
                    lqwPoiApplyItem.eq(PoiApplyItem::getQuarter,poiApply.getQuarter());
                }
                if(ucQuoProjectItem.getLimitType() >=40){
                    lqwPoiApplyItem.eq(PoiApplyItem::getMonth,poiApply.getMonth());
                }
                List<PoiApplyItem> poiApplyItems = poiApplyItemMapper.selectList(lqwPoiApplyItem);
                int numApply = poiApplyItems.stream().mapToInt(PoiApplyItem::getNum).sum();

                if(numApply > numCanApply){
                    throw new ServiceException("申请超出限额");
                }
            }
        }


    }

    @Override
    public int delete(List<Long> ids) {
        for (Long id : ids) {
            QueryWrapper<PoiApplyItem> qwPoiApplyItem = new QueryWrapper<>();
            qwPoiApplyItem.eq("apply_id",id);
            List<PoiApplyItem> poiApplyItems = poiApplyItemMapper.selectList(qwPoiApplyItem);
            List<Long> ids1 = poiApplyItems.stream().map(PoiApplyItem::getId).collect(Collectors.toList());
            poiApplyItemMapper.deleteBatchIds(ids1);
        }
        return baseMapper.deleteBatchIds(ids);
    }

    @Override
    public void poiApplyExamine(PoiApply poiApply) {

        SysUser user = SecurityUtils.getLoginUser().getUser();

        if(poiApply.getPass() == 1){

            PoiApply oldPoiApply = baseMapper.selectById(poiApply.getId());

            UcMyFlow ucMyFlow =new UcMyFlow();
            ucMyFlow.setFlowId(poiApply.getId());
            ucMyFlow.setFlowStatusStart(oldPoiApply.getApplyStatus());
            ucMyFlow.setFlowStatusEnd(300);
            ucMyFlow.setHandleName(user.getNickName());
            ucMyFlow.setPass(poiApply.getPass());
            ucMyFlow.setNotes(poiApply.getNotes());
            ucMyFlow.setDelStatus(1);
            ucMyFlowMapper.insert(ucMyFlow);

            oldPoiApply.setApplyStatus(300);
            baseMapper.updateById(oldPoiApply);

        }else{

            PoiApply oldPoiApply = baseMapper.selectById(poiApply.getId());

            UcMyFlow ucMyFlow =new UcMyFlow();
            ucMyFlow.setFlowId(poiApply.getId());
            ucMyFlow.setFlowStatusStart(oldPoiApply.getApplyStatus());
            ucMyFlow.setFlowStatusEnd(105);
            ucMyFlow.setHandleName(user.getNickName());
            ucMyFlow.setPass(poiApply.getPass());
            ucMyFlow.setNotes(poiApply.getNotes());
            ucMyFlow.setDelStatus(1);
            ucMyFlowMapper.insert(ucMyFlow);

            oldPoiApply.setApplyStatus(105);
            baseMapper.updateById(oldPoiApply);

        }

    }


    @Override
    public void poiApplyReexamine(PoiApply poiApply) {

        SysUser user = SecurityUtils.getLoginUser().getUser();

        if(poiApply.getPass() == 1){

            PoiApply oldPoiApply = baseMapper.selectById(poiApply.getId());

            UcMyFlow ucMyFlow =new UcMyFlow();
            ucMyFlow.setFlowId(poiApply.getId());
            ucMyFlow.setFlowStatusStart(oldPoiApply.getApplyStatus());
            ucMyFlow.setFlowStatusEnd(10000);
            ucMyFlow.setHandleName(user.getNickName());
            ucMyFlow.setPass(poiApply.getPass());
            ucMyFlow.setNotes(poiApply.getNotes());
            ucMyFlow.setDelStatus(1);
            ucMyFlowMapper.insert(ucMyFlow);

            oldPoiApply.setApplyStatus(10000);
            baseMapper.updateById(oldPoiApply);

        }else{

            PoiApply oldPoiApply = baseMapper.selectById(poiApply.getId());

            UcMyFlow ucMyFlow =new UcMyFlow();
            ucMyFlow.setFlowId(poiApply.getId());
            ucMyFlow.setFlowStatusStart(oldPoiApply.getApplyStatus());
            ucMyFlow.setFlowStatusEnd(205);
            ucMyFlow.setHandleName(user.getNickName());
            ucMyFlow.setPass(poiApply.getPass());
            ucMyFlow.setNotes(poiApply.getNotes());
            ucMyFlow.setDelStatus(1);
            ucMyFlowMapper.insert(ucMyFlow);

            oldPoiApply.setApplyStatus(205);
            baseMapper.updateById(oldPoiApply);

        }

    }

    @Override
    public void poiManagement() {

        Date date = new Date();

        QueryWrapper<PoiApply> qwPoiApply = new QueryWrapper<>();
        qwPoiApply.eq("apply_status", 400);
        qwPoiApply.eq("year", DateUtils.getYear(date));
        qwPoiApply.eq("quarter", DateUtils.getQuarter(date));
        qwPoiApply.eq("quota_from", 20);
        List<PoiApply> poiApplies = baseMapper.selectList(qwPoiApply);

        poiApplies.forEach(item -> {
            item.setApplyStatus(10000);
            baseMapper.updateById(item);


            UcMyFlow ucMyFlow =new UcMyFlow();
            ucMyFlow.setFlowId(item.getId());
            ucMyFlow.setFlowStatusStart(400);
            ucMyFlow.setFlowStatusEnd(10000);
            ucMyFlow.setHandleName("定时任务");
            ucMyFlow.setPass(1);
            ucMyFlow.setDelStatus(1);
            ucMyFlowMapper.insert(ucMyFlow);
        });


    }

    @Override
    public PageUtils appListByPage(AppQueryVo appQueryVo) {
        QueryWrapper<PoiApply> qw =new QueryWrapper<>();

        if(appQueryVo.getQUserId()!=null){
            qw.eq("user_id",appQueryVo.getQUserId());
        }
        if(appQueryVo.getQYear()!=null){
            qw.eq("year",appQueryVo.getQYear());
        }
        if(appQueryVo.getQQuarter()!=null){
            qw.eq("quarter",appQueryVo.getQQuarter());
        }
        if(appQueryVo.getQTimeStart()!=null){
            qw.ge("time_start",appQueryVo.getQTimeStart() + " 00:00:00");
        }
        if(appQueryVo.getQTimeEnd()!=null){
            qw.le("time_start",appQueryVo.getQTimeEnd() + " 23:59:59");
        }
        if(appQueryVo.getQStatus()!=null){
            qw.ge("apply_status",appQueryVo.getQStatus());
            qw.le("apply_status",appQueryVo.getQStatus()+5);
        }

        if("descending".equals(appQueryVo.getIsAsc())){
            qw.orderBy(true,false,appQueryVo.getOrderByColumn()).orderBy(true,false,"id");
        }else if("ascending".equals(appQueryVo.getIsAsc())){
            qw.orderBy(true,true,appQueryVo.getOrderByColumn()).orderBy(true,false,"id");
        }else{
            qw.orderBy(true,false,"id");
        }

        IPage<PoiApply> page = this.page(new Query<PoiApply>().getPage(BeanUtil.beanToMap(appQueryVo)), qw);

        return new PageUtils(page);
    }
}
